package com.dengjk.codegenerator.dao.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.db.handler.BeanHandler;
import cn.hutool.db.handler.BeanListHandler;
import cn.hutool.db.sql.SqlExecutor;
import com.alibaba.fastjson.JSON;
import com.dengjk.codegenerator.dao.CodeDao;
import com.dengjk.codegenerator.model.ColumnInfo;
import com.dengjk.codegenerator.model.DbConfig;
import com.dengjk.codegenerator.model.TableInfo;
import com.dengjk.codegenerator.model.TableInfoExt;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.List;

@Repository
@Slf4j
public class CodeDaoImpl implements CodeDao {


    @Override
    @SneakyThrows
    public void saveComment(TableInfo tableInfo, DbConfig dbConfig) {
        Connection conn = getConnection(dbConfig);
        /**修改表 描述*/
        String tableSqlStr = String.format("ALTER TABLE `%s` COMMENT '%s' ;", tableInfo.getTableName(), tableInfo.getComments());
        SqlExecutor.execute(conn, tableSqlStr);
        for (ColumnInfo item : tableInfo.getListColumn()) {
            StringBuilder sb = new StringBuilder();
            sb.append("ALTER TABLE ");
            if (StringUtils.isEmpty(tableInfo.getTableName())) {
                continue;
            } else {
                sb.append(" " + tableInfo.getTableName() + " ");
            }
            sb.append(" MODIFY ");
            if (StringUtils.isEmpty(item.getColName())) {
                continue;
            } else {
                sb.append(" `" + item.getColName() + "` ");
            }
            sb.append(" " + item.getColType() + " ");
            if (!item.isNullable()) {
                sb.append(" NOT NULL ");
            }
            if (!StringUtils.isEmpty(item.getDefaultValue())) {
                if (item.getDefaultValue().contains("CURRENT_TIMESTAMP")) {
                    sb.append(" DEFAULT " + item.getDefaultValue().trim());
                } else {
                    sb.append(" DEFAULT '" + item.getDefaultValue().trim() + "' ");
                }
            }
            if (!StringUtils.isEmpty(item.getExtra())) {
                sb.append(" " + item.getExtra() + " ");
            }
            if (!StringUtils.isEmpty(item.getComments())) {
                sb.append(" COMMENT '" + item.getComments() + "' ;");
            }
            String sqlExecutorStr = sb.toString();
            log.info("修改执行sql:{}", sqlExecutorStr);
            SqlExecutor.execute(conn, sqlExecutorStr);
        }
    }


    /**
     * 查询 所有的表信息
     *
     * @param dbConfig
     * @return
     */
    @Override
    @SneakyThrows
    public List<TableInfo> getAllTables(DbConfig dbConfig) {
        Connection conn = getConnection(dbConfig);
        String sqlStr = "select table_comment as comments,engine as engine_name,table_name,table_rows, truncate(DATA_LENGTH/1024/1024,2) as data_length," +
                "create_time,update_time from information_schema.tables where  table_schema=? order by create_time desc ";
        List<TableInfo> tableList = SqlExecutor.query(conn, sqlStr, BeanListHandler.create(TableInfo.class), dbConfig.getSchema());
        conn.close();
        return tableList;
    }


    /**
     * 查询表 所有的列
     *
     * @param tableName
     * @param dbConfig
     * @return
     */
    @Override
    @SneakyThrows
    public TableInfo getAllColumns(String tableName, DbConfig dbConfig) {
        Connection conn = getConnection(dbConfig);
        String sqlStr = "select table_comment as comments,engine as engine_name,table_name,table_rows,truncate(DATA_LENGTH/1024/1024,3) as data_length," +
                "create_time,update_time from information_schema.tables where table_name=? and table_schema=? ";
        TableInfo tableInfo = SqlExecutor.query(conn, sqlStr, BeanHandler.create(TableInfo.class), tableName, dbConfig.getSchema());
        String sqlColumnStr = "select column_name as colName,column_comment as comments,column_type as colType ,is_nullable as isNull,extra," +
                "column_default as defaultValue from Information_schema.columns where table_name=? and table_schema=? ";
        List<ColumnInfo> colList = SqlExecutor.query(conn, sqlColumnStr, BeanListHandler.create(ColumnInfo.class), tableName, dbConfig.getSchema());
        tableInfo.setColumnCount(colList.size());
        colList.forEach(x -> {
            if (StringUtils.isNotEmpty(x.getExtra())) {
                x.setExtra(StringUtils.remove(x.getExtra(), "DEFAULT_GENERATED"));
            }
            if (StringUtils.isNotEmpty(x.getIsNull())) {
                if (StringUtils.equals("YES", x.getIsNull())) {
                    x.setNullable(true);
                }
            }
            if (StringUtils.isNotEmpty(x.getColType())) {
                if (StringUtils.contains(x.getColType(), "bit")) {
                    x.setColType(StringUtils.replace(x.getColType(), "bit", "tinyint"));
                }
            }
            if (StringUtils.isNotEmpty(x.getDefaultValue())) {
                if (StringUtils.contains(x.getDefaultValue(), "b'0'")) {
                    x.setDefaultValue(StringUtils.replace(x.getDefaultValue(), "b'0'", "0"));
                }
            }
        });
        tableInfo.setListColumn(colList);
        /**多渲染一个 表信息的table*/
        TableInfoExt tableInfoExt = new TableInfoExt();
        BeanUtil.copyProperties(tableInfo, tableInfoExt);
        tableInfo.setTableInfos(Arrays.asList(tableInfoExt));
        conn.close();
        return tableInfo;
    }

    /***
     * 获取数据库连接的函数
     * @param dbConfig
     * @return
     */
    private Connection getConnection(DbConfig dbConfig) {
        try {
            Class.forName(dbConfig.getDriver());
            Connection con = DriverManager.getConnection(dbConfig.getUrl(), dbConfig.getUsername(), dbConfig.getPassword());
            return con;
        } catch (Exception e) {
            log.error("加载数据失败:{}", JSON.toJSONString(dbConfig), e);
            Assert.isTrue(false, "加载数据失败:" + e.getMessage());
        }
        return null;
    }


    /**
     * 测试 链接
     *
     * @param dbConfig
     * @return
     */
    @Override
    public String testConnection(DbConfig dbConfig) {
        Connection connection = getConnection(dbConfig);
        return null;
    }

}
